// META: title=test WebNN API element-wise sub operation
// META: global=window,dedicatedworker
// META: variant=?cpu
// META: variant=?gpu
// META: variant=?npu
// META: script=../resources/utils.js
// META: timeout=long

'use strict';

// https://www.w3.org/TR/webnn/#api-mlgraphbuilder-binary
// Compute the element-wise binary subtraction of the two input tensors.
// MLOperand sub(MLOperand a, MLOperand b);


const getSubPrecisionTolerance = (graphResources) => {
  const toleranceValueDict = {float32: 1, float16: 1};
  const expectedDataType =
      getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
  return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
};

const subTests = [
  {
    'name': 'sub float32 1D constant tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'},
          'constant': true
        },
        'inputB': {
          'data': [
            -49.12813186645508, 40.189292907714844,  7.224666595458984,
            89.26004791259766,  -81.43340301513672,  59.61166000366211,
            11.234410285949707, 48.884056091308594,  85.26825714111328,
            27.695297241210938, 30.98945426940918,   -38.12903594970703,
            -83.14810180664062, -86.16175079345703,  16.75888442993164,
            46.12889862060547,  -28.432477951049805, 28.229337692260742,
            35.2364616394043,   -77.05516815185547,  -57.8714714050293,
            -58.15085983276367, 27.488866806030273,  31.99802017211914
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'},
          'constant': true
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            122.72087097167969,  -25.704608917236328, -76.62667846679688,
            -141.30532836914062, 5.652030944824219,   -61.885711669921875,
            -94.53349304199219,  -33.3062858581543,   -147.96905517578125,
            5.258705139160156,   51.56763458251953,   -36.77735137939453,
            161.37109375,        134.5541534423828,   -35.91242599487305,
            -132.0611114501953,  117.5560302734375,   -5.354707717895508,
            45.33327102661133,   174.68115234375,     110.61997985839844,
            147.31689453125,     -47.992286682128906, 67.48905944824219
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 1D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -49.12813186645508, 40.189292907714844,  7.224666595458984,
            89.26004791259766,  -81.43340301513672,  59.61166000366211,
            11.234410285949707, 48.884056091308594,  85.26825714111328,
            27.695297241210938, 30.98945426940918,   -38.12903594970703,
            -83.14810180664062, -86.16175079345703,  16.75888442993164,
            46.12889862060547,  -28.432477951049805, 28.229337692260742,
            35.2364616394043,   -77.05516815185547,  -57.8714714050293,
            -58.15085983276367, 27.488866806030273,  31.99802017211914
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            122.72087097167969,  -25.704608917236328, -76.62667846679688,
            -141.30532836914062, 5.652030944824219,   -61.885711669921875,
            -94.53349304199219,  -33.3062858581543,   -147.96905517578125,
            5.258705139160156,   51.56763458251953,   -36.77735137939453,
            161.37109375,        134.5541534423828,   -35.91242599487305,
            -132.0611114501953,  117.5560302734375,   -5.354707717895508,
            45.33327102661133,   174.68115234375,     110.61997985839844,
            147.31689453125,     -47.992286682128906, 67.48905944824219
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 2D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -49.12813186645508, 40.189292907714844,  7.224666595458984,
            89.26004791259766,  -81.43340301513672,  59.61166000366211,
            11.234410285949707, 48.884056091308594,  85.26825714111328,
            27.695297241210938, 30.98945426940918,   -38.12903594970703,
            -83.14810180664062, -86.16175079345703,  16.75888442993164,
            46.12889862060547,  -28.432477951049805, 28.229337692260742,
            35.2364616394043,   -77.05516815185547,  -57.8714714050293,
            -58.15085983276367, 27.488866806030273,  31.99802017211914
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            122.72087097167969,  -25.704608917236328, -76.62667846679688,
            -141.30532836914062, 5.652030944824219,   -61.885711669921875,
            -94.53349304199219,  -33.3062858581543,   -147.96905517578125,
            5.258705139160156,   51.56763458251953,   -36.77735137939453,
            161.37109375,        134.5541534423828,   -35.91242599487305,
            -132.0611114501953,  117.5560302734375,   -5.354707717895508,
            45.33327102661133,   174.68115234375,     110.61997985839844,
            147.31689453125,     -47.992286682128906, 67.48905944824219
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 3D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -49.12813186645508, 40.189292907714844,  7.224666595458984,
            89.26004791259766,  -81.43340301513672,  59.61166000366211,
            11.234410285949707, 48.884056091308594,  85.26825714111328,
            27.695297241210938, 30.98945426940918,   -38.12903594970703,
            -83.14810180664062, -86.16175079345703,  16.75888442993164,
            46.12889862060547,  -28.432477951049805, 28.229337692260742,
            35.2364616394043,   -77.05516815185547,  -57.8714714050293,
            -58.15085983276367, 27.488866806030273,  31.99802017211914
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            122.72087097167969,  -25.704608917236328, -76.62667846679688,
            -141.30532836914062, 5.652030944824219,   -61.885711669921875,
            -94.53349304199219,  -33.3062858581543,   -147.96905517578125,
            5.258705139160156,   51.56763458251953,   -36.77735137939453,
            161.37109375,        134.5541534423828,   -35.91242599487305,
            -132.0611114501953,  117.5560302734375,   -5.354707717895508,
            45.33327102661133,   174.68115234375,     110.61997985839844,
            147.31689453125,     -47.992286682128906, 67.48905944824219
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 4D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -49.12813186645508, 40.189292907714844,  7.224666595458984,
            89.26004791259766,  -81.43340301513672,  59.61166000366211,
            11.234410285949707, 48.884056091308594,  85.26825714111328,
            27.695297241210938, 30.98945426940918,   -38.12903594970703,
            -83.14810180664062, -86.16175079345703,  16.75888442993164,
            46.12889862060547,  -28.432477951049805, 28.229337692260742,
            35.2364616394043,   -77.05516815185547,  -57.8714714050293,
            -58.15085983276367, 27.488866806030273,  31.99802017211914
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            122.72087097167969,  -25.704608917236328, -76.62667846679688,
            -141.30532836914062, 5.652030944824219,   -61.885711669921875,
            -94.53349304199219,  -33.3062858581543,   -147.96905517578125,
            5.258705139160156,   51.56763458251953,   -36.77735137939453,
            161.37109375,        134.5541534423828,   -35.91242599487305,
            -132.0611114501953,  117.5560302734375,   -5.354707717895508,
            45.33327102661133,   174.68115234375,     110.61997985839844,
            147.31689453125,     -47.992286682128906, 67.48905944824219
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 5D tensors',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -49.12813186645508, 40.189292907714844,  7.224666595458984,
            89.26004791259766,  -81.43340301513672,  59.61166000366211,
            11.234410285949707, 48.884056091308594,  85.26825714111328,
            27.695297241210938, 30.98945426940918,   -38.12903594970703,
            -83.14810180664062, -86.16175079345703,  16.75888442993164,
            46.12889862060547,  -28.432477951049805, 28.229337692260742,
            35.2364616394043,   -77.05516815185547,  -57.8714714050293,
            -58.15085983276367, 27.488866806030273,  31.99802017211914
          ],
          'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            122.72087097167969,  -25.704608917236328, -76.62667846679688,
            -141.30532836914062, 5.652030944824219,   -61.885711669921875,
            -94.53349304199219,  -33.3062858581543,   -147.96905517578125,
            5.258705139160156,   51.56763458251953,   -36.77735137939453,
            161.37109375,        134.5541534423828,   -35.91242599487305,
            -132.0611114501953,  117.5560302734375,   -5.354707717895508,
            45.33327102661133,   174.68115234375,     110.61997985839844,
            147.31689453125,     -47.992286682128906, 67.48905944824219
          ],
          'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 broadcast 1D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [-97.04911804199219],
          'descriptor': {'dimensions': [1], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            -170.641845703125,   -111.53379821777344, -27.64710235595703,
            -45.00383377075195,  -21.267745971679688, -94.77507019042969,
            -13.750038146972656, -112.62688446044922, -34.34831237792969,
            -130.00311279296875, -179.606201171875,   -22.142730712890625,
            -175.27210998535156, -145.4415283203125,  -77.89557647705078,
            -11.116905212402344, -186.17266845703125, -119.92375183105469,
            -177.6188507080078,  -194.67510986328125, -149.79762268066406,
            -186.21514892578125, -76.54570007324219,  -196.53619384765625
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 broadcast 2D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            10.762838363647461, -90.23992156982422, 12.787367820739746,
            -62.44633865356445, 32.18257522583008, 20.359493255615234
          ],
          'descriptor': {'dimensions': [2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            62.82989501953125,  104.72460174560547,  -82.18938446044922,
            10.401054382324219, -107.96394348144531, -22.633544921875,
            -94.06192016601562, 105.81768798828125,  -75.48817443847656,
            95.40034484863281,  50.374515533447266,  -95.26588439941406,
            67.46015167236328,  138.63232421875,     -31.94091033935547,
            -23.48587417602539, 56.940975189208984,  2.51513671875,
            69.80689239501953,  187.86590576171875,  39.96113967895508,
            151.6123809814453,  -52.68599319458008,  79.12757873535156
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 broadcast 3D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            -8.39311408996582, 75.54753112792969, -32.325870513916016,
            8.088332176208496
          ],
          'descriptor': {'dimensions': [2, 2, 1], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            81.98584747314453,   22.877796173095703,  -61.00890350341797,
            -127.59281921386719, -151.3289031982422,  -77.82157897949219,
            -50.973209381103516, 47.90364074707031,   -30.374935150146484,
            24.86566925048828,   74.46875762939453,   -82.99472045898438,
            86.61610412597656,   56.78551483154297,   -10.760427474975586,
            -161.479736328125,   13.576019287109375,  -52.67290115356445,
            112.89559936523438,  129.9518585205078,   85.07437896728516,
            81.07770538330078,   -28.591751098632812, 91.39874267578125
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'sub float32 broadcast 4D to 4D',
    'graph': {
      'inputs': {
        'inputA': {
          'data': [-97.04911804199219],
          'descriptor': {'dimensions': [1, 1, 1, 1], 'dataType': 'float32'}
        },
        'inputB': {
          'data': [
            73.59273529052734,   14.4846830368042,  -69.40201568603516,
            -52.045284271240234, -75.7813720703125, -2.2740514278411865,
            -83.29907989501953,  15.57776927947998, -62.7008056640625,
            32.954002380371094,  82.55709075927734, -74.90638732910156,
            78.22299194335938,   48.39240264892578, -19.153541564941406,
            -85.93221282958984,  89.12355041503906, 22.874629974365234,
            80.56973266601562,   97.62598419189453, 52.74850845336914,
            89.1660385131836,    -20.50341796875,   99.48707580566406
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'sub',
        'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
        'outputs': 'output'
      }],
      'expectedOutputs': {
        'output': {
          'data': [
            -170.641845703125,   -111.53379821777344, -27.64710235595703,
            -45.00383377075195,  -21.267745971679688, -94.77507019042969,
            -13.750038146972656, -112.62688446044922, -34.34831237792969,
            -130.00311279296875, -179.606201171875,   -22.142730712890625,
            -175.27210998535156, -145.4415283203125,  -77.89557647705078,
            -11.116905212402344, -186.17266845703125, -119.92375183105469,
            -177.6188507080078,  -194.67510986328125, -149.79762268066406,
            -186.21514892578125, -76.54570007324219,  -196.53619384765625
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  }
];

if (navigator.ml) {
  subTests.forEach((test) => {
    webnn_conformance_test(
        buildGraphAndCompute, getSubPrecisionTolerance, test);
  });
} else {
  test(() => assert_implements(navigator.ml, 'missing navigator.ml'));
}
